#ifndef __INC_MEMORY
#define __INC_MEMORY

#include <stdlib.h>
#include "../alu/register.h"

#define MEMORY_SIZE_WORDS 512

/*
 * Represents a bank of memory and two control registers.
 */
typedef struct
{
	/*
	 * A pointer to the first memory location.
	 */
	Register mem_block[MEMORY_SIZE_WORDS];

	/*
	 * The address in memory to read/write from/to.
	 */
	Register mar;

	/*
	 * The data to be written or the data just read.
	 */
	Register mdr;
} Memory;

/*
 * Initializes a new memory bank.
 */
Memory *new_memory(void);

/*
 * Sets the address at which the next read or write will occur.
 * memory: A pointer to the memory to modify.
 * value: The new value to set.
 */
void memory_set_memory_address_register(Memory *memory, Register value);

/*
 * Sets the data to be written to memory.
 * memory: A pointer to the memory to modify.
 * value: The new value to set.
 */
void memory_set_memory_data_register(Memory *memory, Register value);

/*
 * Gets the data most recently read from memory.
 * memory: A pointer to the memory to query.
 */
Register memory_get_memory_data_register(Memory *memory);

/*
 * Gets the memory value at the address register and puts it in the data
 * register. This operation is undefined if the address register hasn't been
 * set.
 * memory: A pointer to the memory to query.
 */
void memory_perform_read(Memory *memory);

/*
 * Sets the memory value at the address register to the value contained in the
 * data register. This operation is undefined if the address register or the
 * data register hasn't been set.
 */
void memory_perform_write(Memory *memory);

/*
 * Frees the memory object from system memory.
 * memory: The memory to delete.
 */
void delete_memory(Memory *memory);

#endif
